package com.jinmdz.fmis.api.admin.service;

import com.jinmdz.fmis.api.admin.model.equipment.EquipmentCellItem;
import com.jinmdz.fmis.api.base.BaseService;
import com.jinmdz.fmis.api.constant.FileConst;
import com.jinmdz.fmis.api.model.config.dictionary.OperationLogCode;
import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.api.wrapper.DictionaryWrapper;
import com.jinmdz.fmis.api.wrapper.DocumentWrapper;
import com.jinmdz.fmis.api.wrapper.OperationWrapper;
import com.jinmdz.fmis.common.ext.StringBuilderExt;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.common.util.DateUtil;
import com.jinmdz.fmis.common.util.third.PoiUtil;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.constant.EDictCode;
import com.jinmdz.fmis.core.exception.ActionException;
import com.jinmdz.fmis.core.util.JacksonUtil;
import com.jinmdz.fmis.dao.model.dictionary.DataDictionaryItem;
import com.jinmdz.fmis.mapper.entity.ColdStorageEquipmentEntity;
import com.jinmdz.fmis.mapper.mapper.ColdStorageEquipmentMapper;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 冷藏冷柜Excel导入Service
 *
 * @author LiCongLu
 * @date 2020-03-11 11:16
 */
@Service("equipmentExcelService")
public class EquipmentExcelService extends BaseService {

    @Resource
    private DictionaryWrapper dictionaryWrapper;

    @Resource
    private ColdStorageEquipmentMapper coldStorageEquipmentMapper;

    @Resource
    private OperationWrapper operationWrapper;

    @Resource
    private OperationLogCode operationLogCode;

    @Resource
    private DocumentWrapper documentWrapper;

    @Resource
    private EquipmentService equipmentService;

    /**
     * 批量导入Excel表格
     *
     * @param userItem        当前帐号
     * @param importExcelFile 表格文件
     * @return
     * @author LiCongLu
     * @date 2020-03-13 09:17
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult importEquipmentWithExcel(UserItem userItem, MultipartFile importExcelFile) throws ActionException {
        // 判断导入文件
        if (DataUtil.isNull(importExcelFile) || importExcelFile.isEmpty()) {
            throw exception("导入文件不存在");
        }
        File excelFile = getExcelTempFile();
        try {
            importExcelFile.transferTo(excelFile);
        } catch (Exception e) {
            throw exception("上传导入文件失败");
        }

        // 执行批量导入操作
        return importEquipmentWithExcel(userItem, excelFile);
    }

    /**
     * 执行批量导入操作
     *
     * @param userItem  当前帐号
     * @param excelFile 导入表格文件
     * @return
     * @author LiCongLu
     * @date 2020-03-13 17:06
     */
    public BaseResult importEquipmentWithExcel(UserItem userItem, File excelFile) throws ActionException {
        // 判断是否上传成功
        if (!excelFile.exists()) {
            throw exception("上传导入文件失败");
        }

        try {
            // 读取表格
            FileInputStream inputStream = new FileInputStream(excelFile);
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            inputStream.close();

            // 类型字典集合
            ArrayList<DataDictionaryItem> typeItems = dictionaryWrapper.listDataDictionaryItem(EDictCode.EQUIPMENT_TYPE);
            // 调整信息结构
            HashMap<String, DataDictionaryItem> typeMap = new HashMap<>(16);
            typeItems.forEach(typeItem -> {
                typeMap.put(typeItem.getDataText(), typeItem);
            });

            // 逗号分割符
            String comma = ",";
            String stop = "停用";

            // 判断文件个数
            int sheetNumber = workbook.getNumberOfSheets();

            for (int index = 0; index < sheetNumber; index++) {
                //获取给定索引处的Sheet对象。
                XSSFSheet sheet = workbook.getSheetAt(index);
                if (sheet == null) {
                    continue;
                }
                // 判断sheet名称是否存在此类型
                String sheetName = sheet.getSheetName();
                if (!typeMap.containsKey(sheetName)) {
                    continue;
                }

                // 设备类型编码
                DataDictionaryItem typeItem = typeMap.get(sheetName);

                // 获取最大行数+1
                int lastRowNum = sheet.getLastRowNum();
                // 获取最大列数
                int lastCellNum = 1;
                for (int i = 1; i < lastRowNum + 1; i++) {
                    Row row = sheet.getRow(i);
                    if (lastCellNum <= row.getLastCellNum()) {
                        lastCellNum = row.getLastCellNum();
                    }
                }

                // 遍历查询
                EquipmentCellItem[][] cellItems = new EquipmentCellItem[lastRowNum][lastCellNum];
                for (int i = 1; i < lastRowNum + 1; i++) {
                    Row row = sheet.getRow(i);
                    cellItems[i - 1] = new EquipmentCellItem[lastCellNum];
                    int cellNum = row.getLastCellNum();
                    for (int j = 1; j <= lastCellNum; j++) {
                        if (j > cellNum) {
                            cellItems[i - 1][j - 1] = null;
                            continue;
                        }
                        Cell cell = row.getCell(j);
                        if (cell == null) {
                            cellItems[i - 1][j - 1] = null;
                            continue;
                        }
                        // 获取数据
                        String cellValue = cell.getStringCellValue();
                        if (DataUtil.valid(cellValue)) {
                            cellValue = cellValue.replace("，", ",");
                            EquipmentCellItem cellItem = new EquipmentCellItem(j, i);
                            if (cellValue.contains(comma)) {
                                String[] values = cellValue.split(comma);
                                cellItem.setCellValue(values[0])
                                        .setDisable(0);
                                if (values.length > 1) {
                                    if (DataUtil.equals(stop, values[1])) {
                                        cellItem.setDisable(1);
                                    }
                                }
                            } else {
                                cellItem.setCellValue(cellValue);
                            }

                            cellItems[i - 1][j - 1] = cellItem;
                        } else {
                            cellItems[i - 1][j - 1] = null;
                        }
                    }
                }

                // 批量新增数据
                insertEquipmentEntities(userItem, typeItem, cellItems, lastRowNum, lastCellNum);
            }
        } catch (Exception ex) {
            throw exception("读取识别异常");
        }

        return success("导入成功");
    }

    /**
     * 插入冷藏冷柜信息
     *
     * @param userItem    当前帐号
     * @param typeItem    类型实体
     * @param cellItems   导入表格
     * @param lastRowNum  最大行数
     * @param lastCellNum 最大列数
     * @return
     * @author LiCongLu
     * @date 2020-03-11 11:18
     */
    private void insertEquipmentEntities(UserItem userItem, DataDictionaryItem typeItem, EquipmentCellItem[][] cellItems, int lastRowNum, int lastCellNum) throws ActionException {

        // 创建索引游标
        int index = 1;

        //  遍历实体
        for (int i = 0; i < lastCellNum; i++) {
            for (int j = 0; j < lastRowNum; j++) {
                EquipmentCellItem cellItem = cellItems[j][i];
                if (cellItem == null) {
                    continue;
                }

                // 创建实体
                ColdStorageEquipmentEntity entity = getEntity(userItem, ColdStorageEquipmentEntity.class);

                // 赋值信息
                entity.setEquipmentTypeCode(typeItem.getDataCode())
                        .setEquipmentCode(cellItem.getCellValue())
                        .setEquipmentDescribe(entity.getEquipmentCode())
                        .setEquipmentState(0)
                        .setColumnNo(cellItem.getColumnNo())
                        .setRowNo(cellItem.getRowNo())
                        .setDisableState(cellItem.getDisable())
                        .setSort(index++);


                // 对冷藏冷柜信息进行判断处理
                equipmentService.checkEquipmentValue(entity);

                // 新增冷藏冷柜信息
                coldStorageEquipmentMapper.insertColdStorageEquipment(entity);
                // 判断保存冷藏冷柜信息结果
                if (DataUtil.invalid(entity.getId())) {
                    throw exception("保存冷藏冷柜接运信息失败");
                }

                // 添加日志
                saveEquipmentEntityLog(userItem, typeItem, cellItem, entity);
            }
        }
    }

    /**
     * 添加冷柜日志
     *
     * @param userItem 当前帐号
     * @param typeItem 冷柜类型
     * @param cellItem 原数据
     * @param entity   冷柜信息
     * @return
     * @author LiCongLu
     * @date 2020-03-14 9:41
     */
    private void saveEquipmentEntityLog(UserItem userItem, DataDictionaryItem typeItem, EquipmentCellItem cellItem, ColdStorageEquipmentEntity entity) throws ActionException {

        // 冷柜设备
        Integer logTypeCode = operationLogCode.getInsert();

        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("导入冷藏冷柜信息，冷藏冷柜类型[{0}][{1}]，冷柜编码[{2}]，冷藏冷柜描述[{3}]，禁用状态值[{4}]，操作人员[{5}]"
                , String.valueOf(typeItem.getDataCode()), typeItem.getDataText()
                , entity.getEquipmentCode(), entity.getEquipmentDescribe(), String.valueOf(entity.getDisableState()), userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, logTypeCode, builder.toString(), JacksonUtil.obj2Json(cellItem), null, JacksonUtil.obj2Json(entity));
    }

    /**
     * 得到临时文件信息
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-03-13 13:20
     */
    private File getExcelTempFile() {
        String newPath = DateUtil.formatPattern(nowDate(), DateUtil.PATTERN_10_PATH);
        String fileName = String.valueOf(System.currentTimeMillis()) + PoiUtil.EXCEL2007;
        File excelPath = new File(documentWrapper.getDirPath(FileConst.DirPath.EXCEL, newPath));
        return new File(excelPath, fileName);
    }
}
